package cuongnh.project.japanesediary.vocabulary.ui.editor.grammar.page.example.section;

import java.util.Set;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.wb.swt.SWTResourceManager;

import cuongnh.project.japanesediary.vocabulary.application.Activator;
import cuongnh.project.japanesediary.vocabulary.common.CommonServices;
import cuongnh.project.japanesediary.vocabulary.common.CommonUtils;
import cuongnh.project.japanesediary.vocabulary.model.Grammar;
import cuongnh.project.japanesediary.vocabulary.model.Sentence;
import cuongnh.project.japanesediary.vocabulary.ui.dialog.AddRelatedSentenceDialog;

public class GrammarExamplesSection extends SectionPart {

	private DataBindingContext m_bindingContext;
	private Grammar grammar;
	private CommonServices commonServices;
	private TableViewer exampleList;
	private Text txtVnMeaning;
	private Text txtEnMeaning;
	private boolean dirtyEditor = false;

	/**
	 * Create the SectionPart.
	 * 
	 * @param parent
	 * @param toolkit
	 * @param style
	 */
	public GrammarExamplesSection(Composite parent, FormToolkit toolkit,
			int style, Grammar grammar, CommonServices commonServices) {
		super(parent, toolkit, style);
		this.commonServices = commonServices;
		this.grammar = grammar;
		initData();
		createClient(getSection(), toolkit);
	}

	public void initData() {
		grammar = commonServices.getGrammarDao().getGrammarWithExamples(
				grammar.getGrammarId());
	}

	/**
	 * Fill the section.
	 */
	private void createClient(Section section, FormToolkit toolkit) {
		section.setText("Examples");
		createToolBar(section);
		Composite container = toolkit.createComposite(section);
		section.setClient(container);
		section.setExpanded(true);

		container.setLayout(new GridLayout(2, false));

		Composite compSentences = new Composite(container, SWT.NONE);
		// compSentences.setLayout(new GridLayout(1, false));
		compSentences.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false,
				false, 1, 4));

		exampleList = new TableViewer(compSentences, SWT.BORDER
				| SWT.FULL_SELECTION);
		Table table = exampleList.getTable();
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 2));
		table.setLinesVisible(true);
		table.setHeaderVisible(true);

		TableViewerColumn tableViewerColumn = new TableViewerColumn(
				exampleList, SWT.NONE);
		TableColumn tblclmnSentence = tableViewerColumn.getColumn();
		tblclmnSentence.setWidth(382);
		tblclmnSentence.setText("Sentence");
		TableColumnLayout tblColumnLayout = new TableColumnLayout();
		tblColumnLayout.setColumnData(tblclmnSentence, new ColumnWeightData(95,
				true));
		compSentences.setLayout(tblColumnLayout);

		exampleList.getTable().addListener(SWT.Selection, new Listener() {

			@Override
			public void handleEvent(Event event) {
				if (dirtyEditor == false && isDirty() == true) {
					commit(false);
					getManagedForm().dirtyStateChanged();
				}
			}

		});

		exampleList
				.addSelectionChangedListener(new ISelectionChangedListener() {

					@Override
					public void selectionChanged(SelectionChangedEvent event) {
						dirtyEditor = isDirty();
						makeExampleEditable(true);
					}
				});

		Label lblVnMeaning = new Label(container, SWT.NONE);
		lblVnMeaning.setFont(SWTResourceManager.getFont("Segoe UI", 10,
				SWT.BOLD));
		GridData gd_lblVnMeaning = new GridData(SWT.FILL, SWT.FILL, true,
				false, 1, 1);
		gd_lblVnMeaning.widthHint = 224;
		lblVnMeaning.setLayoutData(gd_lblVnMeaning);
		lblVnMeaning
				.setForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		lblVnMeaning.setAlignment(SWT.CENTER);
		lblVnMeaning.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_TITLE_BACKGROUND));
		lblVnMeaning.setText("Vietnamese meaning");

		txtVnMeaning = new Text(container, SWT.BORDER | SWT.WRAP | SWT.MULTI);
		txtVnMeaning.setEditable(false);
		txtVnMeaning.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true,
				1, 1));

		Label lblEnMeaning = new Label(container, SWT.NONE);
		lblEnMeaning.setAlignment(SWT.CENTER);
		lblEnMeaning.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				false, 1, 1));
		lblEnMeaning.setFont(SWTResourceManager.getFont("Segoe UI", 10,
				SWT.BOLD));
		lblEnMeaning
				.setForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		lblEnMeaning.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_TITLE_BACKGROUND));
		lblEnMeaning.setText("English meaning");

		txtEnMeaning = new Text(container, SWT.BORDER | SWT.WRAP | SWT.MULTI);
		txtEnMeaning.setEditable(false);
		txtEnMeaning.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true,
				1, 1));

		m_bindingContext = initDataBindings();
		IChangeListener listener = new IChangeListener() {
			@Override
			public void handleChange(ChangeEvent event) {
				makeExampleEditable(true);
				markDirty();
			}
		};

		IObservableList bindings = m_bindingContext.getBindings();

		// Register the listener to all bindings
		for (Object o : bindings) {
			Binding b = (Binding) o;
			b.getTarget().addChangeListener(listener);
			b.getModel().addChangeListener(listener);
		}

		CommonUtils
				.sentencesHookDoubleClickCommand(commonServices, exampleList);
	}

	@Override
	public void commit(boolean onSave) {
		super.commit(onSave);
		commonServices.getGrammarDao().merge(grammar);
		exampleList.refresh();
	}

	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		IObservableValue exampleListObserveSingleSelection = ViewersObservables
				.observeSingleSelection(exampleList);
		IObservableValue exampleListSentenceObserveDetailValue = BeanProperties
				.value(Sentence.class, "vnMeaning", String.class)
				.observeDetail(exampleListObserveSingleSelection);
		IObservableValue observeTextTxtSentenceObserveWidget = WidgetProperties
				.text(SWT.Modify).observe(txtVnMeaning);
		bindingContext.bindValue(exampleListSentenceObserveDetailValue,
				observeTextTxtSentenceObserveWidget, null, null);

		IObservableValue exampleListObserveSingleSelection_1 = ViewersObservables
				.observeSingleSelection(exampleList);
		IObservableValue exampleListVnMeaningObserveDetailValue = BeanProperties
				.value(Sentence.class, "enMeaning", String.class)
				.observeDetail(exampleListObserveSingleSelection_1);
		IObservableValue observeTextTxtVnMeaningObserveWidget = WidgetProperties
				.text(SWT.Modify).observe(txtEnMeaning);
		bindingContext.bindValue(exampleListVnMeaningObserveDetailValue,
				observeTextTxtVnMeaningObserveWidget, null, null);

		ObservableSetContentProvider setContentProvider = new ObservableSetContentProvider();
		IObservableMap[] observeMaps = BeansObservables.observeMaps(
				setContentProvider.getKnownElements(), Sentence.class,
				new String[] { "sentence" });
		exampleList
				.setLabelProvider(new ObservableMapLabelProvider(observeMaps));
		exampleList.setContentProvider(setContentProvider);
		//
		IObservableSet grammarExamplesGrammarObserveSet = BeansObservables
				.observeSet(Realm.getDefault(), grammar, "grammarExamples");
		exampleList.setInput(grammarExamplesGrammarObserveSet);

		return bindingContext;
	}

	private void makeExampleEditable(boolean editable) {
		txtVnMeaning.setEditable(editable);
		txtEnMeaning.setEditable(editable);
	}

	private void createToolBar(Section section) {
		ToolBar toolbar = new ToolBar(section, SWT.FLAT);
		section.setTextClient(toolbar);

		ToolItem addItem = new ToolItem(toolbar, SWT.PUSH);
		addItem.setImage(Activator.getImageDescriptor("/icons/add.gif")
				.createImage());
		addItem.setToolTipText("Add a new related grammar for this grammar");

		addItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				AddRelatedSentenceDialog sentenceWizard = new AddRelatedSentenceDialog(
						getSection().getShell(), commonServices);
				if (sentenceWizard.open() == Window.OK) {
					Set<Sentence> selectedSentences = sentenceWizard
							.getSelectedSentences();
					grammar.getGrammarExamples().addAll(selectedSentences);
					// commonServices.getGrammarDao().update(grammar);
					m_bindingContext.updateModels();
					exampleList.refresh();
					exampleList.setSelection(new StructuredSelection(
							selectedSentences.toArray()));

				}
			}
		});

		ToolItem removeItem = new ToolItem(toolbar, SWT.PUSH);
		removeItem.setImage(Activator.getImageDescriptor("/icons/delete.gif")
				.createImage());
		removeItem
				.setToolTipText("Remove selected related grammar for this grammar");

		removeItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection selection = (IStructuredSelection) exampleList
						.getSelection();
				Set<Sentence> selectedSentences = CommonUtils
						.getSelectedSentences(selection);
				boolean confirm = MessageDialog.openConfirm(getSection()
						.getShell(), "Confirm Delete",
						"Are you sure you want to delete this example?");
				if (confirm) {
					grammar.getGrammarExamples().removeAll(selectedSentences);
					// commonServices.getGrammarDao().update(grammar);
					m_bindingContext.updateModels();
					exampleList.refresh();
					makeExampleEditable(false);
				}
			}
		});
	}

}
